import Watcher from '../watcher.js'
/**
 * html字符串转dom
 * @param {*} html 
 * @returns 
 */
const htmlStringToElement = (html = "") => {
  const template = document.createElement("template")
  template.innerHTML = html.trim()
  return template.content.firstChild
}

/**
 * 收集器更新操作
 * @param {*} watchers 
 * @param {*} value 
 */
const updateWatcher = (watchers = [], value, type) => {
  if (type) {
    watchers.forEach((watcher) => {
      watcher.arrayUpdate(value, type)
    })
  } else {
    watchers.forEach((watcher) => {
      watcher.update(value)
    })
  }
}

/**
 * 将属性值绑定到vue实例上
 * @param {*} vueInstance 
 * @param {*} obj 
 */
const bindProperties = (vueInstance, obj) => {
  for (let key of Object.keys(obj)) {
    vueInstance[key] = obj[key]
  }
}

/**
 * 初始化计算属性
 * @param {*} vueInstance 
 * @param {*} obj 
 */
const initComputed = (vueInstance, obj) => {
  for (let key of Object.keys(obj)) {
    initWatcher(key, vueInstance, node, 'value') // 收集器初始化并收集相关node
  }
}

/**
 * key为数组 ? 获取最后子节点key对应到组件实例中的值 : 获取对应key组件实例中的值
 * @param {*} key
 * @param {*} data
 * @param {*} callBack
 * @returns 
 */
const getInstanceValue = (key, data, callBack) => {
  try {
    if (Object.prototype.toString.call(key) === '[object Array]') {
      if (key.length === 1) {
        if (callBack) {
          callBack()
        }
        return data[key[0]]
      } else {
        return key.reduce((prev, property) => {
          if (callBack) {
            callBack(property)
          }
          return prev[property]
        }, data)
      }
    } else {
      if (callBack) {
        callBack()
      }
      return data[key]
    }
  } catch (e) {
    console.warn(`lve.js提示：获取实例值报错， 报错key为${key}`);
    return ''
  }
}

/**
 * watcher收集器初始化并收集值
 * @param {*} key 
 * @param {*} vueInstance 当前组件对象实例
 * @param {*} node 当前dom节点
 * @param {*} attribute dom属性绑定
 * @param {*} template dom textContent文本值
 */
const initWatcher = (key, vueInstance, node, attribute, template) => {
  const len = key.length
  const firstKey = key[0]
  if (len > 1) { // 引用类型变量
    const lastKey = key[len - 1]
    vueInstance.$watchers[firstKey] = vueInstance.$watchers[firstKey] || {} // 初始化收集器
    vueInstance.$watchers[firstKey][lastKey] = vueInstance.$watchers[firstKey][lastKey] || [] // 初始化收集器
    vueInstance.$watchers[firstKey][lastKey].push(new Watcher(vueInstance, node, attribute, template));
  } else { // 基本类型变量
    vueInstance.$watchers[firstKey] = vueInstance.$watchers[firstKey] || [] // 初始化收集器
    vueInstance.$watchers[firstKey].push(new Watcher(vueInstance, node, attribute, template));
  }
}

/**
 * 判断某属性是否为对象的属性
 * @param {*} parent 
 * @param {*} key 
 */
const deepAttributeInObject = (parent, key) => {
  let flag = false
  const judgeNode = (node) => {
    for (let i in node) {
      if (i === key) {
        flag = true
      } else {
        if (Object.prototype.toString.call(parent[i]) === '[object Object]') {
          judgeNode(node[i], key)
        }
      }
    }
  }
  judgeNode(parent)
  return flag
}

/**
 * 判断当前数据类型
 * @param {*} obj 
 * @returns 
 */
const getDataType = (obj) => {
  const str = Object.prototype.toString.call(obj); // 检测基本类型值，引用类型值的类型
  const map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  };
  if(obj instanceof Element){
    return 'element';
  }
  return map[str];
}

/**
 * 将对象、null、undefined替换成空白字符
 * @param {*} obj 
 */
const replaceObjToBlank = (obj) => {
  const map = {
    'null': 'null',
    '[object Object]': '\[object Object\]',
    'undefined': 'undefined'
  }
  const type = getDataType(obj)
  let res = ''
  if (type === 'string') { // 当设置值为
    const reg = new RegExp(`/(${Object.values(map).join('|')})/`, 'gm')
    res = obj.replaceAll(obj.match(reg), '') // 将所有需转换的字符全都转成空白字符
  } else if (type === 'object') {
    res = obj.toString().replaceAll(reg, '')
  }
  return res
}

/**
 * 清除父节点下非空节点
 * @param {*} ele 
 */
const clearWhitespace = (ele) => {
  for(var i=0;i<ele.childNodes.length;i++){
      var node=ele.childNodes[i];
      if(node.nodeType==3 && !/\S/.test(node.nodeValue)){ // 空白节点首先是文本节点， \S 为匹配非空字符
          node.parentNode.removeChild(node)
      }
  }
}

export {
  htmlStringToElement,
  updateWatcher,
  bindProperties,
  getInstanceValue,
  initWatcher,
  deepAttributeInObject,
  getDataType,
  replaceObjToBlank,
  clearWhitespace
}